Function Review

函数专题 函数域函数式编程

1 函数声明:function fn(){ }

2 函数表达式:应用场景 var fn = function(){ }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
在构造函数中添加方法
function Person(name) {
this.name = name;
this.age = age;
// 在构造函数内部中添加方法
this.getAge = function() {
return this.age;
}
}
// 给原型添加方法
Person.prototype.getName = function() {
return this.name;
}
// 在对象中添加方法
var a = {
m: 20,
getM: function() {
return this.m;
}
}

3 匿名函数:应用场景,自执行以及作为参数传递

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 使用函数自执行的方式创建模块
(function(window, undefined) {
// 声明jQuery构造函数
var jQuery = function(name) {
// 主动在构造函数中,返回一个jQuery实例
return new jQuery.fn.init(name);
}
// 添加原型方法
jQuery.prototype = jQuery.fn = {
constructor: jQuery, //jQuery构造函数的prototype属性上有一个constructor属性,上面一行代码的操作会将prototype指向一个新的对象,所以需要加上这行代码,添加其constructor属性
init:function(name) { ... },//实现选择器功能
css: function() { ... return this} //每次链式编程结束之后都返回实例化对象
}
jQuery.fn.init.prototype = jQuery.fn;//这行代码是jQuery实现链式编程的关键,返回的init构造函数的实例指向了函数jQuery的原型prototype,该原型上有jQuery上封装的API
// 将jQuery改名为$,并将引用保存在window上,形成闭包,对外开发jQuery构造函数,这样我们就可以访问所有挂载在jQuery原型上的方法了
window.jQuery = window.$ = jQuery;//赋值运算,从右至左,返回等号右边的运算数
//window对象多了两个属性,一个是$ 一个是jQuery 都被赋值为jQuery函数,指向jQuer函数地址
})(window);
// 在使用时,我们直接执行了构造函数,因为在jQuery的构造函数中通过一些手段,返回的是jQuery的实例,所以我们就不用再每次用的时候在自己new了
$('#div1');//$(name) 执行的时候,得到返回的 new jQuery.fn.init(name)对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//函数自执行的方式
(function(){
console.log("func is excuted");
})();
(function(){
console.log("func is excuted");
}());
~function(){
console.log("func is excuted");
}();
+function(){
console.log("func is excuted");
}();

4 函数的形参,传入的实参赋值给形参;形参作为变量名成为该函数作用域内的变量;如果实参个数小于形参个数,未被定义的将默认值为undefined

函数的参数是按值传递的,即会将传递的值复制一份到函数的局部变量中;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
//----------------------------------------------------------------------------
//先看一下这个栗子
var a = 10 ;
var obj = {name:"Jhon"};
function fn(a,obj){
a = a + 1 ;
obj.name = "JiM";
console.log(a);
}
fn(a,obj);
console.log(a);
console.log(obj.name);
//-----------------------------------------------------------------------------
//对比理解对象作为参数的传递
var person = {
name: 'Nicholas',
age: 20
}
function setName(obj) { // 传入一个引用
obj = {}; // 将传入的引用指向另外一个空的对象
obj.name = 'Greg'; // 给这个空的对象添加属性
}
setName(person);//类似于 obj = person ;然后回去执行函数,又将obj指向一个空的对象
console.log(person.name); // Nicholas 未被改变
//--------------------------------------------------------
var person = {
name: 'Nicholas',
age: 20
}
function setName(obj) { // 传入一个引用
obj.name = 'Greg'; // 修改引用的name属性
}
setName(person);//将obj指向person 类似于 obj = person;
console.log(person.name); // Greg
//对比以上两种情况,对于基本数据类型,是按值传递的,对于复杂数据类型,也是按值传递的,传递的是复杂数据类型对应的地址值;
//----------------------------------------------------------------------
var c= 5;
//----------------------函数的形参是局部变量
function fn(a,b){ //a = 4 , b = 3 这两个是函数作用域内的变量
d = 6; //这个将会添加给全局作用域
console.log(a+b);
}
fn(4,3);
//----------------------------------------------------------------------------
//传入的实参个数少于形参的个数,未被赋值的形参默认值为undefined
function fn2 (a,b){
console.log(a);//1
console.log(b);//undefined
}
fn2(1);
//-----------------------------------------------------------------------------

5 函数的调用方式:

作为函数体直接执行 作为构造函数调用 作为对象的方法调用 ;

这些都是函数的执行,函数内部的代码都会一行行的执行;

1
2
3
4
5
6
7
function f1(){
console.log(this);
var tmp = 1;
this.x = 3;
console.log(tmp);    //A
console.log(this.x);     //B
}

5.1 函数直接执行

1
console.log(f1());//undefined f1()函数执行后没有返回值,此时默认返回undefined

控制台输出

1
2
3
4
window
1
3
undefined

作为构造函数调用,此时内部的this指向new出来的对象

1
 console.log(new f1());

控制台输出

1
2
3
4
f1{} //这个其实就是new操作符创建的一个空的对象
1
3
f1{x:3}

6 函数简写

7 prototype属性和constructor属性

  • 每个函数都自动拥有一个prototype属性,该属性是一个对象,
  • 函数的prototype属性,包含一个不可枚举的属性constructor ;constructor属性指向该函数
  • 类似形成了一个闭环
1
2
3
4
5
6
7
8
9
10
11
12
function fn (a,b){
fn.age = 19 ;
console.log(a);//1
console.log(b);//undefined
}
console.log(fn.prototype.constructor === fn);//true
var f = new fn();
console.dir(f);
console.log(f.__proto__ === fn.prototype );//true
console.log(f.__proto__.constructor == fn);//true

8 函数的name属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var func1 = function () {};
// ES5
func1.name // ""
// ES6
func1.name // "func1"
//上面代码中,变量func1等于一个匿名函数, ES5 和 ES6 的name属性返回的值不一样。
//如果将一个具名函数赋值给一个变量,则 ES5 和 ES6 的name属性都返回这个具名函数原本的名字。
const bar = function baz() {};
// ES5
bar.name // "baz"
// ES6
bar.name // "baz"
//Function构造函数返回的函数实例,name属性的值为 “anonymous” 。
(new Function).name // "anonymous"
//bind返回的函数,name属性值会加上 “bound ” 前缀。
function foo() {};
foo.bind({}).name // "bound foo"
(function(){}).bind({}).name // "bound "